﻿//Created: 03/24/2013 @ 10:20pm by Azriel Del Monté
//Last changed date: 04/07/2013 @ 03:49am by Azriel Del Monté

using Action = Styx.TreeSharp.Action;
using Styx;
using Styx.Helpers;
using Styx.Common;
using Styx.CommonBot;
using Styx.CommonBot.Routines;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Diagnostics;
using System.Threading;
using System.Windows.Media;

namespace Boogman
{
    public partial class Main : CombatRoutine
    {

        public override string Name { get { return "Hunter Survival by Pasterke"; } }
        public override WoWClass Class { get { return WoWClass.Hunter; } }
        LocalPlayer Me { get { return StyxWoW.Me; } }

        public override bool WantButton { get { return true; } }

        public override void OnButtonPress()
        {
            Form1 ConfigForm = new Form1();
            ConfigForm.ShowDialog();
        }

        #region Initialize
        public override void Initialize()
        {
            //Updater.CheckForUpdate();
            Lua.Events.AttachEvent("MODIFIER_STATE_CHANGED", HandleModifierStateChanged);
        }
        #endregion

        private static ulong lastGuid = 0;

        float shotRange = 39;

        private static Stopwatch fightTimer = new Stopwatch();

        private static Stopwatch pullTimer = new Stopwatch();

        public string LastPetSpell = "";

        public string PetGrowl = "";

        public bool RemoveDeadTargets = true;

        public bool ReadinessGo = false;

        public int teller = 0;

        private double MyTargetDistance
        {
            get
            {
                return Me.GotTarget ? Me.CurrentTarget.Distance : uint.MaxValue - 1;
            }
        }

        public override void Pulse()
        {
            try
            {
                if ((Me.Pet != null
                    || Me.Pet.IsDead)
                    && petPresenceTimer.IsRunning)
                {
                    petPresenceTimer.Reset();
                    return;
                }
                if ((Me.Pet == null
                    || Me.Pet.IsDead)
                    && !Me.Mounted
                    && !Me.IsFlying
                    && !Me.OnTaxi
                    && !Me.IsGhost)
                {
                    petPresenceTimer.Restart();
                    return;
                }
                if (!Me.CurrentTarget.Lootable
                    && Me.CurrentTarget.IsDead
                    && RemoveDeadTargets
                    && Me.CurrentTarget.Distance >= 5)
                {
                    Me.ClearTarget();
                    LogMsg("Looted Target removed (" + Me.CurrentTarget.Name + ")", 1);
                    return;
                }
                if (fightTimer.IsRunning
                    && fightTimer.Elapsed.Seconds >= 30)
                {
                    Blacklist.Add(Me.CurrentTarget, BlacklistFlags.All, new TimeSpan(0, 3, 0));
                    fightTimer.Reset();
                    LogMsg("Take too much time to attack, blacklisting current target", 1);
                    return;
                }
                if (Me.Combat && Me.CurrentTarget.IsFriendly)
                {
                    Me.ClearTarget();
                    LogMsg("Friendly Target removed because I'm in Combat (" + Me.CurrentTarget.Name + ")", 1);
                    return;
                }
                if (!Me.CurrentTarget.IsPlayer && Me.CurrentTarget.IsFriendly)
                {
                    return;
                }
                if (Me.Combat && RemoveDeadTargets && Me.CurrentTarget.IsDead)
                {
                    Me.ClearTarget();
                    LogMsg("Dead Target removed (" + Me.CurrentTarget.Name + ")", 1);
                    return;
                }
                if(!Me.Combat
                    && RapidFireTimer.IsRunning
                    && ReadinessTimer.IsRunning)
                {
                    RapidFireTimer.Reset();
                    ReadinessTimer.Reset();
                    ReadinessGo = false;
                }
                if (Me.Combat
                    && RapidFireTimer.IsRunning
                    && !ReadinessGo)
                {
                    ReadinessTimer.Restart();
                    ReadinessGo = true;
                }

            }
            catch { }
        }

        public override bool NeedRest
        {
            get
            {
                if (UseSpells)
                {
                    if (Me.HealthPercent <= BoogmanSettings.myPrefs.UseBandages)
                    {
                        return true;
                    }
                    if (!Me.IsSwimming)
                    {
                        if (Me.HealthPercent <= BoogmanSettings.myPrefs.EatDrink)
                        {
                            return true;
                        }
                        if (Me.Pet != null
                            && Me.GotAlivePet
                            && Me.Pet.HealthPercent <= BoogmanSettings.myPrefs.mendpetpercent)
                        {
                            return true;
                        }
                    }
                }
                return false;
            }
        }

        public override void Rest()
        {
            if (UseSpells
                && !buffExists(FeignDeath, Me))
            {
                if (Me.Pet != null
                    && Me.GotAlivePet
                    && Me.Pet.HealthPercent <= BoogmanSettings.myPrefs.mendpetpercent
                    )
                {
                    if (Me.Pet != null
                        && !Me.Pet.HasAura(MendPet)
                        && SpellManager.HasSpell(MendPet))
                    {
                        if (SpellManager.CanCast(MendPet))
                        {
                            SpellManager.Cast(MendPet);
                            LogMsg("MendPet Pet", 2);
                        }
                    }
                }
                if (Me.HealthPercent <= BoogmanSettings.myPrefs.UseBandages)
                {
                    UseBandages();
                }
                if (!Me.IsSwimming
                    && !Me.HasAura("First Aid"))
                {
                    if (Me.HealthPercent <= BoogmanSettings.myPrefs.EatDrink
                        && !buffExists(FeignDeath, Me))
                    {
                        Styx.CommonBot.Rest.Feed();
                    }
                }
            }

        }
        public override bool NeedPreCombatBuffs
        {
            get
            {
                if (SpellManager.HasSpell(TrapLauncher)
                    && !buffExists(TrapLauncher, Me)
                    && lastCast != TrapLauncher)
                {
                    if (SpellManager.CanCast(TrapLauncher))
                    {
                        SpellManager.Cast(TrapLauncher, Me);
                        LogMsg("Trap Launcher", 2);
                        lastCast = TrapLauncher;
                    }
                }
                if (SpellManager.HasSpell(AspectIronHawk)
                    && !buffExists(AspectIronHawk, Me)
                    && lastCast != AspectIronHawk)
                {
                    if (SpellManager.CanCast(AspectIronHawk))
                    {
                        SpellManager.Cast(AspectIronHawk);
                        LogMsg("Aspect of the Iron Hawk", 2);
                        lastCast = AspectIronHawk;
                    }
                }
                if (SpellManager.HasSpell(AspectHawk)
                    && !SpellManager.HasSpell(AspectIronHawk)
                    && !buffExists(AspectHawk, Me)
                    && lastCast != AspectHawk)
                {
                    if (SpellManager.CanCast(AspectHawk))
                    {
                        SpellManager.Cast(AspectHawk, Me);
                        LogMsg("Aspect of the Hawk", 2);
                        lastCast = AspectHawk;
                    }
                }
                 
                CallPet();
                ReviveMyPet();
                
                return false;
            }
        }
        public override void PreCombatBuff()
        {
         
        }
        public override void Pull()
        {
            if (buffExists(FeignDeath, Me))
            {
                Me.ClearTarget();
                Thread.Sleep(10000);
                KeyboardManager.KeyUpDown(' ');

            }

            if (!BoogmanSettings.myPrefs.DisableTargetting)
            {
                EnsureTarget();
            }

            if (Me.CurrentTarget.Guid != lastGuid)
            {
                fightTimer.Reset();
                lastGuid = Me.CurrentTarget.Guid;
                LogMsg("Killing " + Me.CurrentTarget.Name + " at distance " + System.Math.Round(MyTargetDistance).ToString() + ".", 3);
                pullTimer.Reset();
                pullTimer.Start();

            }
            else
            {
                if (pullTimer.ElapsedMilliseconds > 30 * 1000)
                {
                    LogMsg("Cannot pull " + Me.CurrentTarget.Name + " now.  Blacklist for 3 minutes.", 3);
                    Blacklist.Add(Me.CurrentTarget.Guid, BlacklistFlags.All, TimeSpan.FromMinutes(3));
                }
            }
            if (!BoogmanSettings.myPrefs.DisableFacing)
            {
                Facing();
            }
            if (Me.CurrentTarget.Distance > shotRange)
            {
                MoveInRange(shotRange);
            }
            else
            {
                LogMsg("Starting attack", 3);
                if (Me.IsMoving)
                {
                    WoWMovement.MoveStop();
                }
                if (Me.Level >= 76)
                {
                    Lua.DoString("RunMacroText('/cast [@pet,exists] Misdirection');");
                    {
                        Logging.Write(Colors.Aqua, ">> Misdirection on Pet <<");
                    }
                }
                if (SpellManager.HasSpell(ConcussiveShot)
                    && !SpellManager.HasSpell(Misdirection)
                    && !spellOnCooldown(ConcussiveShot)
                    && !buffExists(ConcussiveShot, Me.CurrentTarget))
                {
                    if (SpellManager.CanCast(ConcussiveShot))
                    {
                        SpellManager.Cast(ConcussiveShot);
                        LogMsg("Pull with Concussive Shot", 6);
                        lastCast = ConcussiveShot;
                    }
                }
                else if (lastCast != ConcussiveShot)
                {
                    SpellManager.Cast(ArcaneShot);
                    LogMsg("Pull with Arcane Shot", 6);
                }
                if (!Me.Pet.IsAutoAttacking)
                {
                    Lua.DoString("PetAttack()");
                }
                Lua.DoString("StartAttack()");
            }
        }
        

        public override void Combat()
        {
            if (buffExists(FeignDeath, Me))
            {
                return;
            }
            if (UseSpells)
            {
                if (gotTarget
                    && !Me.IsAutoAttacking
                    && (!Me.IsInInstance
                    || !Me.GroupInfo.IsInRaid))
                {
                    Lua.DoString("StartAttack();");
                }
                 
                CallPet();
                ReviveMyPet();
                
                UseMendPet();
                UseTrapLauncer();
                UseAspect();
                AlchemistFlask();
                myPotion();
                myFlask();
                HealthStone();
                MoveInLignOfSight();
                MoveInRange(35);
                Facing();
                TakingPetTarget();
                PetAttack();

                if (UseAoe)
                {
                    AoeRotation();
                }
                if (!UseAoe)
                {
                    MainRotation();
                }
            }
        }
        #region MainRotation

        public void MainRotation()
        {
            if (gotTarget
                && !SpellManager.HasSpell(Misdirection)
                && SpellManager.HasSpell(ConcussiveShot)
                && Me.CurrentTarget.ThreatInfo.RawPercent > 75
                && !spellOnCooldown(ConcussiveShot)
                && !buffExists(ConcussiveShot, Me.CurrentTarget))
            {
                if (SpellManager.CanCast(ConcussiveShot))
                {
                    SpellManager.Cast(ConcussiveShot);
                    LogMsg("Concussive Shot", 3);
                    LastSpell = "Concussive Shot";
                    return;
                }
            }
            if (gotTarget
                && BoogmanSettings.myPrefs.misdirection == 1
                && Me.CurrentTarget.ThreatInfo.RawPercent > 75
                && SpellManager.HasSpell(Misdirection)
                && !buffExists(Misdirection, Me)
                && !spellOnCooldown(Misdirection)
                && LastSpell != "Misdirection")
            { 
                Lua.DoString("RunMacroText('/cast [@focus,help][help][@pet,exists] Misdirection');");   
                LogMsg(">> Misdirection <<", 3);
                LastSpell = "Misdirection";
            }
            if (gotTarget
                && SpellManager.HasSpell(SilencingShot)
                && !spellOnCooldown(SilencingShot)
                && (Me.CurrentTarget.IsCasting
                && Me.CanInterruptCurrentSpellCast))
            {
                if (SpellManager.CanCast(SilencingShot))
                {
                    SpellManager.Cast(SilencingShot);
                    LogMsg("Silencing Shot", 0);
                    LastSpell = "Silencing Shot";
                    return;
                }
                
            }
            if (gotTarget
                && SpellManager.HasSpell(SerpentSting)
                && !debuffExists(118253, Me.CurrentTarget)
                && LastSpell != "Serpent Sting")
            {
                if (SpellManager.CanCast(SerpentSting))
                {
                    SpellManager.Cast(SerpentSting);
                    LogMsg("Serpent Sting", 6);
                    return;
                }

            }
            if (gotTarget
                && SpellManager.HasSpell(ExplosiveShot)
                && Me.HasAura("Lock and Load"))
            {
                if (SpellManager.CanCast(ExplosiveShot))
                {
                    SpellManager.Cast(ExplosiveShot);
                    LogMsg("Explosive Shot", 1);
                    LastSpell = "Explosive Shot";
                    return;
                }
                
            }
            if (gotTarget
                && SpellManager.HasSpell(ExplosiveShot)
                && !spellOnCooldown(ExplosiveShot)
                && Me.FocusPercent >= 25)
            {
                if (SpellManager.CanCast(ExplosiveShot))
                {
                    SpellManager.Cast(ExplosiveShot);
                    LogMsg("Explosive Shot", 3);
                    LastSpell = "Explosive Shot";
                    return;
                }
                
            }
            if (gotTarget
                && SpellManager.HasSpell(DireBeast)
                && !spellOnCooldown(DireBeast))
            {
                if (SpellManager.CanCast(DireBeast))
                {
                    SpellManager.Cast(DireBeast);
                    LogMsg("Dire Beast", 2);
                    LastSpell = "Dire Beast";
                    return;
                }
                
            }
            if (gotTarget
                && SpellManager.HasSpell(MurderOfCrows)
                && !spellOnCooldown(MurderOfCrows)
                && !buffExists(MurderOfCrows, Me.CurrentTarget)
                && Crows
                && Me.FocusPercent >= 60)
            {
                if (SpellManager.CanCast(MurderOfCrows))
                {
                    SpellManager.Cast(MurderOfCrows);
                    LogMsg("A Murder of Crows", 3);
                    LastSpell = "A Murder of Crows";
                    return;
                }
                
            }
            if (gotTarget
                && useCDs
                && SpellManager.HasSpell(Stampede)
                && !spellOnCooldown(Stampede) 
                && Stamp)
            {
                if (SpellManager.CanCast(Stampede))
                {
                    SpellManager.Cast(Stampede);
                    LogMsg("Stampede", 4);
                    LastSpell = "Stampede";
                    return;
                }
                
            }
            if (gotTarget
                && SpellManager.HasSpell(BloodFury)
                && !spellOnCooldown(BloodFury)
                && Bloodfury)
            {
                if (SpellManager.CanCast(BloodFury))
                {
                    SpellManager.Cast(BloodFury);
                    LogMsg("Blood Fury", 4);
                    LastSpell = "Blood Fury";

                }
            }
            if (gotTarget
                && SpellManager.HasSpell(Berserking)
                && !spellOnCooldown(Berserking)
                && berserKing)
            {
                if (SpellManager.CanCast(Berserking))
                {
                    SpellManager.Cast(Berserking);
                    LogMsg("Berserking", 4);
                    LastSpell = "Berserking";
                }
            }
            if(gotTarget
                && SpellManager.HasSpell(Lifeblood)
                && !spellOnCooldown(Lifeblood)
                && lifeblood)
            {
                if (SpellManager.CanCast(Lifeblood))
                {
                    SpellManager.Cast(Lifeblood);
                    LogMsg("Lifeblood", 1);
                    LastSpell = "Lifeblood";
                }
            }

            UseTrinket1();
            UseTrinket2();
            UseEngiGloves();

            if (gotTarget
                && SpellManager.HasSpell(RapidFire)
                && !Me.HasAura("Bloodlust")
                && !Me.HasAura("Heroism")
                && !Me.HasAura("Time Warp")
                && lastCast != RapidFire
                && Rapidfire)
            {
                if (SpellManager.CanCast(RapidFire))
                {
                    SpellManager.Cast(RapidFire);
                    LogMsg("Rapid Fire", 2);
                    return;
                }
                
            }
            if (gotTarget
                && SpellManager.HasSpell(Readiness)
                && !buffExists(RapidFire, Me)
                && !spellOnCooldown(Readiness)
                && ReadinessGo)
            {
                if (SpellManager.CanCast(Readiness))
                {
                    SpellManager.Cast(Readiness);
                    LogMsg("Readiness", 2);
                    LastSpell = "Readiness";
                    return;
                }
                
            }
            if (gotTarget
                && SpellManager.HasSpell(KillShot)
                && !spellOnCooldown(KillShot)
                && Me.CurrentTarget.HealthPercent <= 20)
            {
                if (SpellManager.CanCast(KillShot))
                {
                    SpellManager.Cast(KillShot);
                    LogMsg("Kill Shot", 7);
                    return;
                }
            }
            if (gotTarget
                && SpellManager.HasSpell(BlackArrow)
                && !spellOnCooldown(BlackArrow)
                && !debuffExists(BlackArrow, Me.CurrentTarget)
                && Focus >= 35)
            {
                if (SpellManager.CanCast(BlackArrow))
                {
                    SpellManager.Cast(BlackArrow);
                    LogMsg("Black Arrow", 5);
                    return;
                }  
            }
            if (gotTarget
                && SpellManager.HasSpell(GlaiveToss)
                && !spellOnCooldown(GlaiveToss)
                && Focus >= 15)
            {
                if (SpellManager.CanCast(GlaiveToss))
                {
                    if (!Me.IsInInstance
                        && !Me.GroupInfo.IsInRaid
                        && SpellManager.HasSpell(Misdirection)
                        && !buffExists(Misdirection, Me)
                        && !spellOnCooldown(Misdirection))
                    { 
                        Lua.DoString("RunMacroText('/cast [@focus,help][help][@pet,exists] Misdirection');");
                        LogMsg(">> Misdirection <<", 3);
                    }
                    SpellManager.Cast(GlaiveToss);
                    LogMsg("Glaive Toss", 8);
                    return;
                }
            }
            if (gotTarget
                && SpellManager.HasSpell(ArcaneShot)
                && Me.FocusPercent > 61)
            {
                if (SpellManager.CanCast(ArcaneShot))
                {
                    SpellManager.Cast(ArcaneShot);
                    LogMsg("Arcane Shot", 9);
                    return;
                }
                
            }
            if (gotTarget
                && SpellManager.HasSpell(ConcussiveShot)
                && Me.CurrentTarget.IsTargetingMeOrPet
                && !spellOnCooldown(ConcussiveShot)
                && !debuffExists(ConcussiveShot, Me.CurrentTarget))
            {
                if (SpellManager.CanCast(ConcussiveShot))
                {
                    SpellManager.Cast(ConcussiveShot);
                    LogMsg("Concussive Shot", 3);
                }
            }
            if (gotTarget
                && Me.Level >= 81
                && SpellManager.HasSpell(CobraShot)
                && Me.FocusPercent <= 45)
            {
                if (SpellManager.CanCast(CobraShot))
                {
                    SpellManager.Cast(CobraShot);
                    LogMsg("Cobra Shot", 10);
                    return;
                }
                
            }
            if (gotTarget
                && Me.Level < 81
                && SpellManager.HasSpell(SteadyShot)
                && Me.FocusPercent <= 45)
            {
                if (SpellManager.CanCast(SteadyShot))
                {
                    SpellManager.Cast(SteadyShot);
                    LogMsg("Steady Shot", 10);
                    return;
                }
                
            }
        }

        #endregion

        #region AoeRotation

        public void AoeRotation()
        {

            if (gotTarget
                && SpellManager.HasSpell(Misdirection)
                && BoogmanSettings.myPrefs.misdirection == 1
                && (Me.GroupInfo.IsInRaid
                || Me.IsInInstance)
                && Me.CurrentTarget.ThreatInfo.RawPercent > 75
                && !buffExists(Misdirection, Me)
                && !spellOnCooldown(Misdirection)
                && LastSpell != "Misdirection")
            { 
                    Lua.DoString("RunMacroText('/cast [@focus,help][help][@pet,exists] Misdirection');");
                    LogMsg(">> Misdirection <<", 6);
                    LastSpell = "Misdirection";
                    
            }
            if (gotTarget
                && SpellManager.HasSpell(MultiShot)
                && Me.FocusPercent >= 40)
            {
                if (SpellManager.CanCast(MultiShot))
                {
                    if (!Me.IsInInstance 
                        && !Me.GroupInfo.IsInRaid
                        && !buffExists(Misdirection, Me)
                        && !spellOnCooldown(Misdirection)
                        && LastSpell != "Misdirection")
                    { 
                        Lua.DoString("RunMacroText('/cast [@focus,help][help][@pet,exists] Misdirection');");
                        {
                             LogMsg(">> Misdirection <<", 6);
                             LastSpell = "Misdirection";
                        }
                    }
                    SpellManager.Cast(MultiShot);
                    LogMsg("Multi Shot", 6);
                    return;
                }
                
            }
            if (gotTarget
                && SpellManager.HasSpell(ExplosiveTrap)
                && !spellOnCooldown(ExplosiveTrap)
                && buffExists(TrapLauncher, Me)
                && LastSpell != "Explosive Trap")
            {
                Lua.DoString("CastSpellByName('Explosive Trap');");
                {
                    SpellManager.ClickRemoteLocation(StyxWoW.Me.CurrentTarget.Location);
                    LogMsg(">> Explosive Trap <<", 6);
                    LastSpell = "Explosive Trap";
                }
            }
            if (gotTarget
                && Me.Level >= 81
                && SpellManager.HasSpell(CobraShot)
                && Me.FocusPercent <= 41)
            {
                if (SpellManager.CanCast(CobraShot))
                {
                    SpellManager.Cast(CobraShot);
                    LogMsg("Cobra Shot", 6);
                    LastSpell = "Cobra Shot";
                    return;
                }
                
            }
            if (gotTarget
                && Me.Level < 81
                && SpellManager.HasSpell(SteadyShot)
                && Me.FocusPercent <= 41)
            {
                if (SpellManager.CanCast(SteadyShot))
                {
                    SpellManager.Cast(SteadyShot);
                    LogMsg("Steady Shot", 6);
                    LastSpell = "Steady Shot";
                    return;
                }
            }
        }

        #endregion
         
        #region Methods

        #region Buff Checks

        public bool buffExists(int Buff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.GetAuraById(Buff);
                if (Results != null)
                    return true;
            }
            return false;
        }

        public double buffTimeLeft(int Buff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.GetAuraById(Buff);
                if (Results != null)
                {
                    if (Results.TimeLeft.TotalMilliseconds > 0)
                        return Results.TimeLeft.TotalMilliseconds;
                }
            }
            return 0;
        }

        public uint buffStackCount(int Buff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.GetAuraById(Buff);
                if (Results != null)
                    return Results.StackCount;
            }
            return 0;
        }
        #endregion

        #region Cache Checks
        public IEnumerable<WoWAura> cachedAuras = new List<WoWAura>();
        public IEnumerable<WoWAura> cachedTargetAuras = new List<WoWAura>();
        public void getCachedAuras()
        {
            if (Me.CurrentTarget != null)
                cachedTargetAuras = Me.CurrentTarget.GetAllAuras();
            cachedAuras = Me.GetAllAuras();
        }
        #endregion

        #region Cooldown Checks
        private Dictionary<WoWSpell, long> Cooldowns = new Dictionary<WoWSpell, long>();
        public TimeSpan cooldownLeft(int Spell)
        {
            SpellFindResults Results;
            if (SpellManager.FindSpell(Spell, out Results))
            {
                WoWSpell Result = Results.Override ?? Results.Original;
                if (Cooldowns.TryGetValue(Result, out lastUsed))
                {
                    if (DateTime.Now.Ticks < lastUsed)
                        return Result.CooldownTimeLeft;
                    return TimeSpan.MaxValue;
                }
            }
            return TimeSpan.MaxValue;
        }
        long lastUsed;
        public int lastCast;
        public bool onCooldown(int Spell)
        {
            SpellFindResults Results;
            if (SpellManager.FindSpell(Spell, out Results))
            {
                WoWSpell Result = Results.Override ?? Results.Original;
                if (Cooldowns.TryGetValue(Result, out lastUsed))
                {
                    if (DateTime.Now.Ticks < lastUsed)
                        return Result.Cooldown;
                    return false;
                }
            }
            return false;
        }
        public TimeSpan spellCooldownLeft(int Spell, bool useTracker = false)
        {
            if (useTracker)
                return cooldownLeft(Spell);
            SpellFindResults results;
            if (SpellManager.FindSpell(Spell, out results))
            {
                if (results.Override != null)
                    return results.Override.CooldownTimeLeft;
                return results.Override.CooldownTimeLeft;
            }
            return TimeSpan.MaxValue;
        }
        public bool spellOnCooldown(int Spell, bool useTracker = false)
        {
            if (useTracker)
                return !onCooldown(Spell);
            SpellFindResults results;
            if (SpellManager.FindSpell(Spell, out results))
                return results.Override != null ? results.Override.Cooldown : results.Original.Cooldown;
            return false;
        }
        #endregion

        #region Debuff Checks

        public bool debuffExists(int Debuff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                WoWAura aura = onTarget.GetAllAuras().FirstOrDefault(a => a.SpellId == Debuff && a.CreatorGuid == Me.Guid);
                if (aura != null) 
                { 
                    return true; 
                }
            }
            return false;
        }

        public double debuffTimeLeft(int Debuff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                WoWAura aura = onTarget.GetAllAuras().FirstOrDefault(a =>
                    a.SpellId == Debuff
                    && a.CreatorGuid == Me.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.TimeLeft.TotalMilliseconds;
            }
            return 0;
        }

        public uint debuffStackCount(int Debuff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                WoWAura aura = onTarget.GetAllAuras().FirstOrDefault(a =>
                    a.SpellId == Debuff
                    && a.CreatorGuid == Me.Guid);

                if (aura == null)
                {
                    return 0;
                } 
                return aura.StackCount;
            }
            return 0;
        }
        #endregion

        #region Focus checks
        public double Focus
        {
            get
            {
                try
                {
                    using (StyxWoW.Memory.AcquireFrame())
                    {
                        return Styx.WoWInternals.Lua.GetReturnVal<int>("return UnitPower(\"player\");", 0);
                    }
                }
                catch { return 0; }
            }
        }
        #endregion

        #region Macro Checks
        public bool Manual { get { return Convert.ToBoolean(Lua.GetReturnVal<int>("return Manual and 0 or 1", 0)); } }
        public bool useCDs { get { return Convert.ToBoolean(Lua.GetReturnVal<int>("return useCDs and 0 or 1", 0)); } }
        #endregion

        #region Target Checks

        internal IEnumerable<WoWUnit> attackableTargets
        {
            get { return ObjectManager.GetObjectsOfType<WoWUnit>(true, false).Where(U => U.Attackable && U.CanSelect && !U.IsFriendly && !U.IsDead && !U.IsNonCombatPet && !U.IsCritter); }
        }

        public bool gotTarget { get { return Me.GotTarget && Me.CurrentTarget != null && Me.CurrentTarget.Attackable && (!Me.CurrentTarget.IsDead && !Me.CurrentTarget.IsFriendly || isTargetDummy); } }
        
        public bool isTargetDummy { get { return Me.CurrentTarget.Name == "Training Dummy" || Me.CurrentTarget.Name == "Raider's Training Dummy"; } }
        
        internal IEnumerable<WoWUnit> nearbyTargets(WoWPoint fromLocation, double Radius)
        {
            var Hostile = attackableTargets;
            var maxDistance = Radius * Radius;
            return Hostile.Where(x => x.Location.DistanceSqr(fromLocation) < maxDistance);
        }
        
        public double targetDistance(WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.DistanceSqr;
                if (Results != null)
                    return onTarget.DistanceSqr;
            }
            return 0;
        }
        public double targetHP(WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.HealthPercent;
                if (Results != null)
                    return onTarget.HealthPercent;
            }
            return 0;
        }
        #endregion

        #region Timer Checks
        private int conv_Date2Timestam(DateTime _time)
        {
            var date1 = new DateTime(1970, 1, 1);
            DateTime date2 = _time;
            var ts = new TimeSpan(date2.Ticks - date1.Ticks);
            return (Convert.ToInt32(ts.TotalSeconds));
        }
        private uint current_life;
        private int current_time;
        private ulong guid;
        private uint first_life;
        private uint first_life_max;
        private int first_time;
        public long targetExistence(WoWUnit onTarget)
        {
            if (onTarget == null) return 0;
            if (isTargetDummy) return 9999;
            if (onTarget.CurrentHealth == 0 || onTarget.IsDead || !onTarget.IsValid || !onTarget.IsAlive)
                return 0;
            if (guid != onTarget.Guid)
            {
                guid = onTarget.Guid;
                first_life = onTarget.CurrentHealth;
                first_life_max = onTarget.MaxHealth;
                first_time = conv_Date2Timestam(DateTime.Now);
            }
            current_life = onTarget.CurrentHealth;
            current_time = conv_Date2Timestam(DateTime.Now);
            var time_diff = current_time - first_time;
            var hp_diff = first_life - current_life;
            if (hp_diff > 0)
            {
                var full_time = time_diff * first_life_max / hp_diff;
                var past_first_time = (first_life_max - first_life) * time_diff / hp_diff;
                var calc_time = first_time - past_first_time + full_time - current_time;
                if (calc_time < 1) calc_time = 99;
                var time_to_die = calc_time;
                var fight_length = full_time;
                return time_to_die;
            }
            if (hp_diff < 0)
            {
                guid = onTarget.Guid;
                first_life = onTarget.CurrentHealth;
                first_life_max = onTarget.MaxHealth;
                first_time = conv_Date2Timestam(DateTime.Now);
                return -1;
            }
            if (current_life == first_life_max)
                return 9999;
            return -1;
        }
        #endregion

        #endregion
    }
}


